import {computed, defineComponent, ref, toRaw} from 'vue';
import { dynamicConditionProps } from './props';
import { ConditionNode, DynamicConditionAST, GroupNode } from './types/node';
import { Col, Row, Select, Input, Button, ColProps, message, Tooltip } from 'ant-design-vue';
import { CONDITION_TYPE } from './enums/ConditionType';
import { LOGIC_TYPE } from './enums/LogicType';
import {
  PlusSquareOutlined,
  DownOutlined,
  UpOutlined,
  MinusSquareOutlined,
} from '@ant-design/icons-vue';
import { useButtonDropdown } from './hooks/useDropdown';
import { useConditionASTStore } from './store';
import { useSavePopoverButton } from './hooks/useSavePopoverButton';
import { DynamicConditionProps, FormSchema } from './types/schemas';
import { componentMap } from './components/componentsMap';
import { deepClone } from '/@/utils/deepClone';

export default defineComponent({
  name: 'YlDynamicCondition',
  props: dynamicConditionProps,
  emits: [
    'search',
    'searchConditionSelect',
    'update:value',
    'reset',
    'save',
    'searchConditionSelectDel',
  ],
  setup(props, { emit }) {
    const fieldOptions = props.fromSchemas?.map((i) => ({ value: i.field, ...i })) || [];

    const defaultSchemas = props.fromSchemas?.map((i) => deepClone(i) as FormSchema);

    const conditionTypeOptions = Object.values(CONDITION_TYPE);
    const logicTypeOptions = Object.values(LOGIC_TYPE);
    const layoutOptions = props.layoutOption!;
    const groupColSpan = computed(() => 24 / layoutOptions.cols);
    const sizeMap = {
      small: '12px',
      large: '16px',
      default: '14px',
    };
    const fontSizeStyle = computed(() => ({ fontSize: sizeMap[props.size as string] }));

    // 构建默认的条件AST
    function buildDefaultConditionGroup() {
      const defaultConditionGroup = {
        conditions: [
          {
            type: '',
            field: defaultSchemas?.[0]?.field,
            value: defaultSchemas?.[0]?.defaultValue,
            // valueType: {
            //     type: undefined
            // },
            nodeType: 'ConditionNode',
            logicType: 'and',
          },
        ],
        logicType: 'and',
        nodeType: 'GroupNode',
      };
      const defaultConditionGroups = defaultSchemas?.map((schema) => {
        return {
          conditions: [
            {
              type: '',
              field: schema.field,
              value: schema.defaultValue,
              // valueType: {
              //     type: undefined
              // },
              logicType: 'and',
              nodeType: 'ConditionNode',
            },
          ],
          logicType: 'and',
          nodeType: 'GroupNode',
        };
      });
      return {
        defaultConditionGroup,
        defaultConditionGroups,
      };
    }

    const { defaultConditionGroup, defaultConditionGroups } = buildDefaultConditionGroup();

    const conditionAst = ref<DynamicConditionAST>({
      groups: [deepClone(defaultConditionGroup) as unknown as GroupNode],
      key: '',
      name: '',
    });
    const currentConditionKey = ref<string>('');

    // 条件组件组（属性选择组件、条件选择组件、属性值输入组件）
    function useConditionComponents(_conditionNode: ConditionNode & { _tempSchema?: FormSchema }) {

      const conditionNode = toRaw(_conditionNode);
      const currentOption = (defaultSchemas?.find((i) => i.field === conditionNode.field) ||
        {}) as FormSchema;
      conditionNode._tempSchema = {
        ...currentOption,
        componentProps: currentOption.componentProps
          ? {
              ...currentOption.componentProps,
            }
          : {},
      };
      const _conditionTypeOptions = conditionNode._tempSchema?.conditionTypes
        ? conditionTypeOptions.filter((c) =>
            conditionNode._tempSchema?.conditionTypes?.includes(c.value),
          )
        : [];

      function initFormat() {
        if (!conditionNode.field) {
          //@ts-ignore
          conditionNode.field = fieldOptions.length > 0 ? fieldOptions[0].field : undefined;
        }

        if (!conditionNode.type) {
          //@ts-ignore
          conditionNode.type =
            _conditionTypeOptions.length > 0 ? _conditionTypeOptions[0].value : undefined;
        }

        if (!conditionNode._tempSchema?.componentProps) {
          conditionNode._tempSchema!.componentProps = {};
        }

        if ([CONDITION_TYPE.in.value, CONDITION_TYPE.not_in.value].includes(conditionNode.type)) {
          conditionNode._tempSchema!.componentProps.mode = 'multiple';
        }
      }

      initFormat();

      //@ts-ignore
      function onConditionSelect(val, item) {
        // 清楚多选
        if (![CONDITION_TYPE.in.value, CONDITION_TYPE.not_in.value].includes(val)) {
          if (
            conditionNode._tempSchema!.componentProps &&
            conditionNode._tempSchema!.componentProps.mode
          ) {
            delete conditionNode._tempSchema!.componentProps.mode;
          }
        }
        conditionNode._tempSchema = item;
        _conditionNode.value = undefined;
      }

      function onPropSelect() {
        //@ts-ignore
        _conditionNode.type = undefined;
        _conditionNode.value = undefined;
      }

      const inputComponent = computed(() => {
        let comp = conditionNode._tempSchema?.component || Input;
        if (typeof comp === 'string') {
          comp = componentMap.get(comp) || Input;
        }
        return comp;
      });

      const PropValueInput = () => {
        const Comp = inputComponent.value;
        //@ts-ignore
        return (
          <Comp
            {...conditionNode._tempSchema?.componentProps}
            placeholder={'请输入查询值'}
            vModel={[_conditionNode.value, 'value']}
            size={props.size}
            class={'dc-w-100'}
          ></Comp>
        );
      };

      const PropSelect = () => (
        <Select
          placeholder={'请选择查询属性'}
          size={props.size}
          class={'dc-w-100 '}
          vModel={[_conditionNode.field, 'value']}
          onChange={onPropSelect}
          options={fieldOptions}
        ></Select>
      );
      const ConditionSelect = () => (
        <Select
          placeholder={'请选择查询条件'}
          size={props.size}
          class={'dc-w-100 '}
          vModel={[_conditionNode.type, 'value']}
          onChange={onConditionSelect}
          options={_conditionTypeOptions}
        ></Select>
      );

      return {
        PropSelect,
        ConditionSelect,
        PropValueInput,
      };
    }

    //按钮组逻辑实现
    function useButtonGroup() {
      const isMore = ref(false);

      // ast存储逻辑
      const { getConditionASTs, saveConditionAST, delConditionAST, getConditionAST } =
        useConditionASTStore(props.storeOption!);

      function reset() {
        conditionAst.value.groups = [deepClone(defaultConditionGroup) as unknown as GroupNode];
        isMore.value = false;
        emit('reset');
      }

      // 规范化条件节点
      function normalConditionNodeAst() {
        const nodes = deepClone(conditionAst.value.groups) as GroupNode[];
        console.log(nodes);
        return nodes
          .map((i) => {
            i.conditions = i.conditions
              .filter((condition) => ![undefined, null, ''].includes(condition.value))
              .map((conditionNode: ConditionNode & { _tempSchema?: FormSchema }) => {
                // 删除临时属性
                if (conditionNode._tempSchema) {
                  delete conditionNode._tempSchema;
                }
                return conditionNode;
              });
            return i;
          })
          .filter((i) => i.conditions.length > 0);
      }

      function search() {
        const nodes = normalConditionNodeAst();
        emit('search', nodes);
        emit('update:value', nodes);
      }

      async function onSearchSelect(val: string) {
        const ast = await getConditionAST(val);
        if (ast) {
          conditionAst.value = ast;
          isMore.value = true;
          emit('searchConditionSelect', ast);
        }
      }

      async function onSearchSelectDel(val: string) {
        await delConditionAST(val);
        message.success('删除成功');
        emit('searchConditionSelectDel', val);
      }

      function moreFilter() {
        isMore.value = !isMore.value;
        if (!isMore.value) {
          conditionAst.value.groups = [
            (conditionAst.value.groups[0] || defaultConditionGroup) as unknown as GroupNode,
          ];
        } else {
          if (defaultConditionGroups && defaultConditionGroups.length > 0) {
            // @ts-ignore
            defaultConditionGroups[0] = conditionAst.value.groups[0];
          }
          conditionAst.value.groups = defaultConditionGroups as unknown as GroupNode[];
        }
      }

      function renderButtonGroup(colProps?: ColProps) {
        // 下拉选项按钮组件逻辑
        const { ButtonDropdown, addOption } = useButtonDropdown({
          //@ts-ignore
          size: props.size,
          type: 'primary',
          buttonText: '搜索',
          value: currentConditionKey,
          options: () =>
            getConditionASTs().then((res) => res.map((i) => ({ label: i.name, value: i.key }))),
          onItem: onSearchSelect,
          onItemDel: onSearchSelectDel,
        });

        // 保存Popover按钮逻辑
        const { SaveButtonPopover } = useSavePopoverButton(
          props as unknown as DynamicConditionProps,
          emit,
          conditionAst,
          addOption,
          saveConditionAST,
        );

        const ButtonGroup = () => (
            <Col span={24} {...colProps}>
              <Row>
                <Col span={props.showMoreButton ? 18 : 24}>
                  <div class={isMore.value ? 'text-left' : 'text-right'}>
                    <Button class={'dc-m-r-5px'} size={props.size} onClick={reset}>
                      重置
                    </Button>
                    {isMore.value && <SaveButtonPopover></SaveButtonPopover>}
                    <ButtonDropdown class={'dc-m-r-10px'} onClick={search}></ButtonDropdown>
                    {isMore.value && (
                        <Button type="primary" ghost size={props.size} onClick={addGroupNode}>
                          添加条件组
                        </Button>
                    )}
                  </div>
                </Col>
                {props.showMoreButton && (
                    <Col span={6}>
                      <div class={'dc-text-right'}>
                        <Button size={props.size} type="link" onClick={moreFilter}>
                          {isMore.value ? (
                              <>
                                收起
                                <UpOutlined style={fontSizeStyle.value} />
                              </>
                          ) : (
                              <>
                                更多筛选
                                <DownOutlined style={fontSizeStyle.value} />
                              </>
                          )}
                        </Button>
                      </div>
                    </Col>
                )}
              </Row>
            </Col>
        );
        return <ButtonGroup></ButtonGroup>;
      }

      return {
        isMore,
        renderButtonGroup,
      };
    }

    // 按钮组
    const { renderButtonGroup, isMore } = useButtonGroup();

    // 渲染条件组
    function renderGroup(groupNode: GroupNode, g_index: number) {
      return (
        <>
          <Row gutter={20}>
            <Col span={3} class={'dc-w-100'}>
              {g_index != 0 && (
                <div class={'dc-flex dc-align-items-center'}>
                  <Select
                    size={props.size}
                    class={'dc-w-100 '}
                    vModel={[groupNode.logicType, 'value']}
                    options={logicTypeOptions}
                  ></Select>
                </div>
              )}
            </Col>
            <Col span={21}>
              {groupNode.conditions.map((conditionNode, index) => (
                <Row class={'dc-m-b-10px'} gutter={5}>
                  {renderCondition(groupNode, conditionNode, g_index, index)}
                </Row>
              ))}
            </Col>
          </Row>
        </>
      );
    }

    // 渲染默认的条件节点
    function renderDefaultCondition(conditionNode: ConditionNode) {
      const { PropValueInput, ConditionSelect, PropSelect } = useConditionComponents(conditionNode);

      return () => (
        <Row gutter={10}>
          <Col span={4}>
            <PropSelect></PropSelect>
          </Col>
          <Col span={4}>
            <ConditionSelect></ConditionSelect>
          </Col>

          <Col span={8}>
            <PropValueInput></PropValueInput>
          </Col>
        </Row>
      );
    }

    // 添加默认的条件节点
    function addDefaultConditionNode(groupNode: GroupNode, index: number) {
      console.log(index);
      groupNode.conditions.push(deepClone(defaultConditionGroup.conditions[0]) as ConditionNode);
    }

    // 删除条件节点
    function delConditionNode(groupNode: GroupNode, index: number) {
      groupNode.conditions.splice(index, 1);
    }

    function addGroupNode() {
      conditionAst.value.groups.push(deepClone(defaultConditionGroup) as GroupNode);
    }

    function delGroupNode(index: number) {
      conditionAst.value.groups.splice(index, 1);
    }

    // 渲染条件节点
    function renderCondition(
      groupNode: GroupNode,
      conditionNode: ConditionNode,
      g_index: number,
      index: number,
    ) {
      const { PropValueInput, ConditionSelect, PropSelect } = useConditionComponents(conditionNode);

      return () => {
        return (
          <>
            <Col span={3}>
              {index === 0 ? (
                <div class={'dc-w-100 dc-text-14px dc-text-weight-600'}>
                  <span class={'dc-inline-block'} style={fontSizeStyle.value}>
                    第{g_index + 1}组
                  </span>
                  {g_index != 0 && (
                    <Tooltip title={'删除分组'}>
                      <MinusSquareOutlined
                        style={'color: red'}
                        class={'dc-cursor-pointer dc-m-l-5px dc-text-16px'}
                        onClick={() => delGroupNode(g_index)}
                      />
                    </Tooltip>
                  )}
                </div>
              ) : (
                <Select
                  size={props.size}
                  class={'dc-w-100 '}
                  vModel={[conditionNode.logicType, 'value']}
                  options={logicTypeOptions}
                ></Select>
              )}
            </Col>
            <Col span={5}>
              <PropSelect></PropSelect>
            </Col>
            <Col span={4}>
              <ConditionSelect></ConditionSelect>
            </Col>

            <Col span={9}>
              {/*@ts-ignore*/}
              <PropValueInput></PropValueInput>
            </Col>
            <Col span={3}>
              <div class={'dc-flex dc-align-items-center dc-h-100'}>
                <PlusSquareOutlined
                  class={'dc-cursor-pointer dc-m-l-5px dc-text-16px'}
                  onClick={() => addDefaultConditionNode(groupNode, index)}
                />
                {index != 0 && (
                  <MinusSquareOutlined
                    style={'color: red'}
                    class={'dc-cursor-pointer dc-m-l-5px dc-text-16px'}
                    onClick={() => delConditionNode(groupNode, index)}
                  />
                )}
              </div>
            </Col>
          </>
        );
      };
    }

    return () => (
      <div class={'dc-m-y-20px dc-bg-fff'}>
        <Row gutter={40}>
          {isMore.value ? (
            conditionAst.value.groups.map((groupNode, index) => (
              <Col class={'dc-m-b-20px'} span={groupColSpan.value}>
                {renderGroup(groupNode, index)}
              </Col>
            ))
          ) : (
            <Col span={18}>
              {renderDefaultCondition(conditionAst.value.groups[0].conditions[0])}
            </Col>
          )}
          {renderButtonGroup({
            span: isMore.value ? 24 : 6,
          })}
        </Row>
      </div>
    );
  },
});
